/*-----------------------------------------------------------------*
  Project:  NetAgent AM - include
  File:     AMProtect.h

  Copyright NetAgent Co. Ltd., All rights reserved.

  Revision 1.20 2009/04/14
  TWLモード(HYBRID/LTD)に対応
  内部処理を改変
  暗号鍵変更の実施

  Revision 1.10 2009/03/10
  特定条件下でクラッシュする可能性があたバグを修正
  暗号鍵変更の実施

  Revision 1.08 2008/12/25
  暗号鍵変更の実施（これまでも実施されていたが非アナウンス）

  Revision 1.07 2008/12/14
  ヘッダファイルにエラーチェックを追記

  Revision 1.06 2008/11/12
  関数ポインタの保持方法および内部処理を改変

  Revision 1.05 2008/08/21
  バージョンの打ち直しを実施

  Revision 0.3  2008/07/25
  エミュレータ検出関数の追加

  Revision 0.2  2008/04/26
  DEBUG, RELEASEモード時でのensata,IS-NITRO-EMULATOR,
  IS-NITRO-DEBUGGERの検出抑制

  Revision 0.1  2008/03/16
  初期バージョン

 *-----------------------------------------------------------------*/


#ifndef _AM_PROTECT_H_
#define _AM_PROTECT_H_

#include <nitro.h>
#include <nitro/types.h>
#include <nitro/os.h>
#include <nitro/card.h>

#define AM_VERSION (120)

/* -- 関数ポインタ操作用定義 ------------------------------------- */
#define _ADD_VAL        ((u32)(8 * 100))
#define _SET_FUNC(x)    (((u32)x) + (_ADD_VAL))
#define _GET_FUNC(x)    (((u32)x) - (_ADD_VAL))

typedef void (*AM_PTR_FUNC)(void);

/* 実体関数をエクスポート */
#ifdef __cplusplus
extern "C" {
#endif

extern u32 ProtectA1(u32 *addr);    // AM_IsMagiconA1の実体
extern u32 ProtectA2(u32 *addr);    // AM_IsMagiconA2の実体
extern u32 ProtectA3(u32 *addr);    // AM_IsMagiconA3の実体
extern u32 NotProtectA1(u32 *addr); // AM_IsNotMagiconA1の実体
extern u32 NotProtectA2(u32 *addr); // AM_IsNotMagiconA2の実体
extern u32 NotProtectA3(u32 *addr); // AM_IsNotMagiconA3の実体


/*-----------------------------------------------------------------*
  Name:         AM_IS_MAGICON_A

  Description:  検知ルーチンAを使用してマジコン検知を行います。
                実装上の注意をよく読んだ上でご利用ください。
                ※FINALROM版以外ではNITRO-IS-EMULATORは検出対象外に
                なります。

  Arguments:    検知した場合に実行されるvoid(*func)()型の関数アドレ
                ス.関数アドレスにNULLを指定するとそのまま検知の有無
                を意味するu32型のデータが返る.関数アドレスを指定する
                とその関数を実行した後検知の有無を意味するu32型の
                データが返る.

  Returns:      検出
 *-----------------------------------------------------------------*/
#ifdef SDK_FINALROM
#define AM_IsMagiconA1(x)    ProtectA1((u32 *)x)
#define AM_IsMagiconA2(x)    ProtectA2((u32 *)x)
#define AM_IsMagiconA3(x)    ProtectA3((u32 *)x)

#else /* SDK_FINALROM */
/* DEBUG,RELEASE版では公式開発環境でのチェックを抑制する */
static u32 AM_IsMagiconA1(void *func) {

	// LockIDの空き確認
	// LockIDを使い切っているようであればOS_Panic()
	s32 lockId = OS_GetLockID();
	if (OS_LOCK_ID_ERROR == lockId) {
		OS_Panic("lock ID get error.");
	}
	OS_ReleaseLockID((u16)lockId);


	switch (OS_GetConsoleType() & OS_CONSOLE_MASK) {
	case OS_CONSOLE_ENSATA:
	case OS_CONSOLE_ISEMULATOR:
	case OS_CONSOLE_ISDEBUGGER:
#ifdef OS_CONSOLE_TWLDEBUGGER
	case OS_CONSOLE_TWLDEBUGGER:
#endif
		return 0;
	default:
		;
	}

	return ProtectA1((u32 *)func);

}

static u32 AM_IsMagiconA2(void *func) {

	switch (OS_GetConsoleType() & OS_CONSOLE_MASK) {
	case OS_CONSOLE_ENSATA:
	case OS_CONSOLE_ISEMULATOR:
	case OS_CONSOLE_ISDEBUGGER:
#ifdef OS_CONSOLE_TWLDEBUGGER
	case OS_CONSOLE_TWLDEBUGGER:
#endif
		return 0;
	default:
		;
	}

	return ProtectA2((u32 *)func);

}

static u32 AM_IsMagiconA3(void *func) {

	switch (OS_GetConsoleType() & OS_CONSOLE_MASK) {
	case OS_CONSOLE_ENSATA:
	case OS_CONSOLE_ISEMULATOR:
	case OS_CONSOLE_ISDEBUGGER:
#ifdef OS_CONSOLE_TWLDEBUGGER
	case OS_CONSOLE_TWLDEBUGGER:
#endif
		return 0;
	default:
		;
	}

	return ProtectA3((u32 *)func);

}

#endif /* SDK_FINALROM */


/*-----------------------------------------------------------------*
  Name:         AM_ISNOT_MAGICON_A

  Description:  検知ルーチンAを使用してマジコン検知を行います。
                実装上の注意をよく読んだ上でご利用ください。
                ※FINALROM版以外ではNITRO-IS-EMULATORは検出対象外に
                なります。

  Arguments:    検知しない場合に実行されるvoid(*func)()型の関数アドレ
                ス.関数アドレスにNULLを指定するとAM_IsMagiconAと同じ

  Returns:      検出
 *-----------------------------------------------------------------*/
#ifdef SDK_FINALROM
#define AM_IsNotMagiconA1(x) NotProtectA1((u32 *)x)
#define AM_IsNotMagiconA2(x) NotProtectA2((u32 *)x)
#define AM_IsNotMagiconA3(x) NotProtectA3((u32 *)x)

#else /* SDK_FINALROM */
/* DEBUG,RELEASE版では公式開発環境でのチェックを抑制する */
static u32 AM_IsNotMagiconA1(void *func) {

	// LockIDの空き確認
	// LockIDを使い切っているようであればOS_Panic()
	s32 lockId = OS_GetLockID();
	if (OS_LOCK_ID_ERROR == lockId) {
		OS_Panic("lock ID get error.");
	}
	OS_ReleaseLockID((u16)lockId);


	switch (OS_GetConsoleType() & OS_CONSOLE_MASK) {
	case OS_CONSOLE_ENSATA:
	case OS_CONSOLE_ISEMULATOR:
	case OS_CONSOLE_ISDEBUGGER:
#ifdef OS_CONSOLE_TWLDEBUGGER
	case OS_CONSOLE_TWLDEBUGGER:
#endif
		if (NULL != func) {
			((AM_PTR_FUNC)func)();
		}
		return 1;
	default:
		;
	}

	return NotProtectA1((u32 *)func);

}

static u32 AM_IsNotMagiconA2(void *func) {

	switch (OS_GetConsoleType() & OS_CONSOLE_MASK) {
	case OS_CONSOLE_ENSATA:
	case OS_CONSOLE_ISEMULATOR:
	case OS_CONSOLE_ISDEBUGGER:
#ifdef OS_CONSOLE_TWLDEBUGGER
	case OS_CONSOLE_TWLDEBUGGER:
#endif
		if (NULL != func) {
			((AM_PTR_FUNC)func)();
		}
		return 1;
	default:
		;
	}

	return NotProtectA2((u32 *)func);

}

static u32 AM_IsNotMagiconA3(void *func) {

	switch (OS_GetConsoleType() & OS_CONSOLE_MASK) {
	case OS_CONSOLE_ENSATA:
	case OS_CONSOLE_ISEMULATOR:
	case OS_CONSOLE_ISDEBUGGER:
#ifdef OS_CONSOLE_TWLDEBUGGER
	case OS_CONSOLE_TWLDEBUGGER:
#endif
		if (NULL != func) {
			((AM_PTR_FUNC)func)();
		}
		return 1;
	default:
		;
	}

	return NotProtectA3((u32 *)func);

}

#endif /* SDK_FINALROM */


#ifdef __cplusplus
}
#endif


/* _AM_PROTECT_H_ */
#endif


/* --------------------------------------------------------- EOF --*/